package app
{
	import app.db.GoRemoteConnection;
	
	import data.CONST;
	import data.VAR;
	import flash.events.MouseEvent;
	import flash.net.Responder;
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	import mx.events.ListEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;
	import mx.utils.ObjectUtil;
	
	/**
	 * @desc: GoItemGetter handles the following:
	 *   getCategoryList(): gets categories from db.
	 *   getFeedList(): gets feeds from selected category (from db)
	 *   getArticleList(): gets articles from selected feed (from httpservice)
	 *   getArticleContent(): gets content from selected article
	 * @author: thomas fricke
	 * @version 1.1.0
	 **/
	public class GoItemGetter
	{
		// connection related:
		private var gateway:GoRemoteConnection;			// gateway for connections
		public var htserv:HTTPService;
		
		// content related:
		[Bindable] public var categoryList:Array;
		[Bindable] public var categoryIDs:Array;
		[Bindable] public var feedList:Array;
		[Bindable] public var recFeedList:Array;
		[Bindable] public var articleList:Array;
		[Bindable] public var result_format:String = "feed";
		[Bindable] public var articleContent:String;
		[Bindable] public var selectedArticle:int;
		
		
		// getting categories from database:
		public function getCategoryList():void {
			gateway = new GoRemoteConnection(CONST.GATEWAY_LOC);
			gateway.call("GoDBHandler.getCatCount", new Responder(getCategoryListResult, onFault), CONST.UID);
			trace("\'---> getCategoryList() called, waiting for result");
		}
		
		// handling result:
		public function getCategoryListResult(result:Array):void {
			categoryList = new Array();
			categoryIDs = new Array();
			if(result) {
				for(var ii:int = 0; ii <= result.length-1; ii++) {
					categoryList[ii] = result[ii]['cname'];
					categoryIDs[ii] = result[ii]['cid'];
				}
			} else {
				Alert.show("You don't have any categories set yet.");
			}
			trace("  |---> getCategoryListResult() returned categoryList, proceeding...");			
		}

		// getting feeds from database:
		/** here the _real_ id of the categories from db has to be used for preventing clusterfuck. **/
		public function getFeedList(selected:int):void {
			gateway = new GoRemoteConnection(CONST.GATEWAY_LOC);
			gateway.call("GoDBHandler.getFeedsFromCategory", new Responder(getFeedListResult, onFault), selected, CONST.UID);
			trace("\'---> getFeedList() called, waiting for result");			
		}
		
		// handling result:
		public function getFeedListResult(result:Array):void {
			if(result == null) {
				feedList = new Array("");
				Alert.show(CONST.CATEGORY_EMPTY_WARNING);
			} else {
				feedList = new Array("");
				for(var ii:int = 0; ii < result.length; ii++) {
					feedList[ii] = result[ii];
				}
			}
			trace("  |---> getFeedListResult() returned feedList, proceeding...");			
		}

		// getting recommended feeds from database:
		public function getRecommendedFeeds():void {
			gateway = new GoRemoteConnection(CONST.GATEWAY_LOC);
			gateway.call("GoDBHandler.getRecommendedFeedList", new Responder(getRecommendedFeedsResult, onFault));
			trace("\'---> getRecommendedFeeds() called, waiting for result");			
		}
		
		// handling result:
		public function getRecommendedFeedsResult(result:Array):void {
			if(result == null) {
				recFeedList = new Array("");
				Alert.show(CONST.CATEGORY_EMPTY_WARNING);
			} else {
				recFeedList = new Array("");
				for(var ii:int = 0; ii < result.length; ii++) {
					recFeedList[ii] = result[ii]; 
				}
			}
			trace("  |---> getRecommendedFeedsResult() returned feedList, proceeding...");			
		}
		// selected feeds from the GoDGCheckBoxIR will be deleted here:
		public function deleteSelectedFeeds(event:MouseEvent):void {
			trace("Delete selected feeds? " + ObjectUtil.toString(VAR.feeds_to_delete));
			gateway = new GoRemoteConnection(CONST.GATEWAY_LOC);
			for(var ii:int = 0; ii < VAR.feeds_to_delete.length; ii++) {
				gateway.call("GoDBHandler.deleteFeed", new Responder(deleteFeedResult, onFault), VAR.feeds_to_delete[ii]['fid'], 1);
			}
		}
		
		private function deleteFeedResult(result:Boolean):void {
			trace("  |---> Feed deleted.");
		}
		
		// setting up httpservice:
		public function getArticleList(event:ListEvent):void {
			var currentUrl:String = CONST.HTPROXY + event.currentTarget.selectedItem.furl;	// gives url
			var currentName:String = event.currentTarget.selectedItem.fname;				// gives name
			CONST.CURRENT_FEED_URL = currentUrl;
			htserv = new HTTPService();
			htserv.url = CONST.CURRENT_FEED_URL;
			htserv.addEventListener(ResultEvent.RESULT, getArticleListData);
			htserv.send();			
		}
		
		// getting articles from htservice:	
		[Bindable] public var feedResult:ArrayCollection = new ArrayCollection();	// contains rss data in whatever format.
		public function getArticleListData(re:ResultEvent):void {
			articleList = new Array("");
			trace("\'---> getArticleListData() called, waiting for result");
			gateway = new GoRemoteConnection(CONST.GATEWAY_LOC);
			if(articleList.length > 0) {
				articleList = new Array();
			}
			if(re.result is String) {
				trace("  |---o error: result format differing from expected format...");
			} else {			// check result format, probably only use else {
				// RSS 2.0 format catcher
				if(re.result.rss) {
					result_format = "rss";
					trace("\'---> output format: re.result.rss");
					for(var ii:int = 0; ii < re.result.rss.channel.item.length; ii++) {
						articleList.push(re.result.rss.channel.item[ii]['link']);
						feedResult = re.result.rss.channel.item;
					}
				// atom rss format catcher
				} else if(re.result.feed) {	
					result_format = "feed";
					trace("\'---> output format: re.result.feed");
					for(var oo:int = 0; oo < re.result.feed.entry.length; oo++) {
						articleList.push(re.result.feed.entry[oo]['link'].href);
						feedResult = re.result.feed.entry;
					}
				} else if(re.result.RDF) {	// for e.g. heise rdf format
					result_format = "rdf";
					trace("\'---> output format: re.result.RDF");
					for(var uu:int = 0; uu < re.result.RDF.item.length; uu++) {
						articleList.push(re.result.RDF.item[uu]['link']);
						feedResult = re.result.RDF.item;
					}
				} else {
					trace("  |---o error: result format differing from expected format...");
				}
				gateway.call("GoDBHandler.getArticlesVisited", new Responder(getArticleListResult, onFault), articleList);
				trace("\'---> correct result format, proceeding...");
			}			
		}

		[Bindable] public var resultLinks:Array;
		private function getArticleListResult(result:*):void {		// specify type later
			resultLinks = new Array();
			if(result) {
				for(var ii:int = 0; ii < result.length; ii++) {
					resultLinks.push(result[ii]['alink']);			// collects all visited links
				}
			}
			trace("\'---> now scanning database for articles with status \"read\":");
			for(var oo:int = 0; oo < articleList.length; oo++) {			// all links from one feed
				// compare feed links array with result links array:
				for(var uu:int = 0; uu < resultLinks.length; uu++) {	// all visited links from that feed
					if(articleList[oo] == resultLinks[uu]) {
						trace("\  |---> found item: " + articleList[oo]);
						// calling the itemrenderer to set fontweight:
						if(htserv.lastResult.rss) {
							htserv.lastResult.rss.channel.item[oo].isVisited = true;
	            			htserv.lastResult.rss.channel.item.refresh();
	     				} else if(htserv.lastResult.feed) {
							htserv.lastResult.feed.entry[oo].isVisited = true;
	            			htserv.lastResult.feed.entry.refresh();
	     				} else if(htserv.lastResult.RDF) {
							htserv.lastResult.RDF.item[oo].isVisited = true;
	            			htserv.lastResult.RDF.item.refresh();
	     				}
					}
				}
			}
		}
		
		// getting content of specific article (if needed & cannot
		// be done with the getArticleList() functionality/return):
		public function getArticleContent():void {
			// probably not neccessary.
		}
	
		private function onFault(result:Array):void {
			trace("  |---o an error occured: result format differing or database connection broken.");
		}
		
		// resets dataprovider-arrays when called, so datagrids don't contain old data
		public function reset():void {
			this.feedResult = new ArrayCollection();
			this.articleContent = "";
		}

		// singleton:
		private static var instance:GoItemGetter;
		private static var allowInstance:Boolean;
				
		// calling singleton instance:
		public static function getSingleton():GoItemGetter {
			if(instance == null) {
				allowInstance = true;
				instance = new GoItemGetter();
				trace("\'---> getSingleton() successfully called");
				allowInstance = false;
			}
			return instance;
		}
		
		public function GoItemGetter()
		{
			if (!allowInstance) {
// 				throw new Error("Error: Instantiation failed: Use GoItemGetter.getSingleton() instead of new.");
 				trace("  |---o an error occured: Singleton-instantiation failed (use GoItemGetter.getSingleton())");
			}
		}

	}
}